import json
import re

import django_redis
from django.contrib.auth import login, authenticate, logout
from django.http import JsonResponse
from django.views import View

from apps.carts.utils import merge_cart_cookie_to_redis
from apps.users.models import User, Address
from celery_tasks.email.tasks import send_verify_email
from meiduo_mall.settings import EMAIL_VERIFY_URL
from utils.views import LoginRequiredJsonMixin, JWTManager


# Create your views here.


class UsernameCountView(View):
    def get(self, request, username):
        count = User.objects.filter(username__exact=username).count()
        return JsonResponse(data={'code': 0, 'count': count, 'errmsg': ''})


class MobileCountView(View):
    def get(self, request, mobile):
        count = User.objects.filter(mobile__exact=mobile).count()

        return JsonResponse(data={'code': 0, 'count': count, 'errmsg': ''})


class RegisterView(View):
    def post(self, request):
        data = json.loads(request.body.decode())
        username = data.get('username')
        password = data.get('password')
        password2 = data.get('password2')
        mobile = data.get('mobile')
        sms_code = data.get('sms_code')
        allow = data.get('allow')

        if not all([username, password, password2, mobile, sms_code, allow]):
            return JsonResponse(data={'code': 400, 'errmsg': '参数不全'})

        if not re.match(r'^[a-zA-Z0-9_]{5,20}$', username):
            return JsonResponse(data={'code': 400, 'errmsg': '用户名不符合要求'})

        if not re.match(r'^[0-9A-Za-z]{5,20}$', password):
            return JsonResponse({'code': 400, 'errmsg': '密码不符合要求'})

        if password != password2:
            return JsonResponse(data={'code': 400, 'errmsg': '两次密码不一致'})

        redis_sms_code = django_redis.get_redis_connection('code')

        if redis_sms_code.decode() != sms_code:
            return JsonResponse(data={'code': 400, 'errmsg': '验证码错误/失效'})

        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return JsonResponse(data={'code': 400, 'errmsg': '手机号不符合要求'})

        if not allow:
            return JsonResponse(data={'code': 400, 'errmsg': '未同意条款'})

        try:
            user = User.objects.create_user(username=username, password=password, mobile=mobile)
            login(request, user)
        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': '注册失败'})

        return JsonResponse({'code': 0, 'errmsg': ''})


class LoginView(View):

    def post(self, request):
        data = json.loads(request.body.decode())

        username = data.get('username')
        password = data.get('password')
        remembered = data.get('remembered')

        if not all([username, password]):
            return JsonResponse({'code': 400, 'errmsg': '参数错误'})

        if re.match(r'^1[3-9]\d{9}$', username):
            User.USERNAME_FIELD = 'mobile'

        user = authenticate(username=username, password=password)

        if user is None:
            return JsonResponse({'code': 400, 'errmsg': '账户/密码错误'})

        login(request, user)

        response = JsonResponse({'code': 0, 'errmsg': ''})

        response = merge_cart_cookie_to_redis(request, user, response)

        if remembered:
            request.session.set_expiry(60 * 60 * 12 * 30)
            response.set_cookie('username', user.username, max_age=60 * 60 * 12 * 30)
        else:
            request.session.set_expiry(0)
            response.set_cookie('username', user.username)
        return response


class LogoutView(View):
    def delete(self, request):
        logout(request)

        response = JsonResponse({'code': 0, 'errmsg': ''})

        response.delete_cookie('username')

        return response


class CenterView(LoginRequiredJsonMixin, View):
    def get(self, request):
        user = request.user
        info_data = {
            'username': user.username,
            'email': user.email,
            'mobile': user.mobile,
            'email_active': user.email_active
        }

        return JsonResponse(data={'code': 0, 'errmsg': '', 'info_data': info_data})


class EmailView(View):

    def put(self, request):
        data = json.loads(request.body.decode())

        email = data.get('email')

        if email is None:
            return JsonResponse({'code': 400, 'errmsg': '参数错误'})

        user = request.user

        user.email = email
        user.save()

        jwt_manager = JWTManager()
        token = jwt_manager.turn_to_token({'id': user.id, 'email': user.email})
        verify_url = f'{EMAIL_VERIFY_URL}?token={token}'

        send_verify_email.delay(email, verify_url)

        return JsonResponse({'code': 0, 'errmsg': ''})


class VerifyEmailView(View):

    def put(self, request):
        jwt_manager = JWTManager()

        token = request.GET.get('token')
        data = jwt_manager.turn_back_data(token)

        if data is None:
            return JsonResponse({'code': 400, 'errmsg': '错误请求'})

        try:

            user = User.objects.get(pk=data.get('id'), email=data.get('email'))

        except User.DoesNotExist:

            return JsonResponse({'code': 400, 'errmsg': '错误请求'})

        else:
            user.email_active = True

            user.save()

            return JsonResponse({'code': 0, 'errmsg': ''})


class CreateAddressView(View):
    def post(self, request):
        data = json.loads(request.body.decode())

        receiver = data.get('receiver')
        province_id = data.get('province_id')
        city_id = data.get('city_id')
        district_id = data.get('district_id')
        place = data.get('place')
        mobile = data.get('mobile')
        tel = data.get('tel')
        email = data.get('email')

        address = Address.objects.create(
            user=request.user,
            title=receiver,
            receiver=receiver,
            province_id=province_id,
            city_id=city_id,
            district_id=district_id,
            place=place,
            mobile=mobile,
            tel=tel,
            email=email
        )

        if request.user.default_address is None:
            request.user.default_address = address

        request.user.save()

        address_dict = {
            "id": address.id,
            "title": address.title,
            "receiver": address.receiver,
            "province": address.province.name,
            "city": address.city.name,
            "district": address.district.name,
            "place": address.place,
            "mobile": address.mobile,
            "tel": address.tel,
            "email": address.email
        }

        return JsonResponse({'code': 0, 'errmsg': '新增地址成功', 'address': address_dict})


class AddressView(LoginRequiredJsonMixin, View):
    def get(self, request):

        addresses = Address.objects.filter(user=request.user, is_deleted=False)

        address_dict_list = []

        for address in addresses:
            address_dict = {
                "id": address.id,
                "title": address.title,
                "receiver": address.receiver,
                "province": address.province.name,
                "city": address.city.name,
                "district": address.district.name,
                "place": address.place,
                "mobile": address.mobile,
                "tel": address.tel,
                "email": address.email
            }

            default_address = request.user.default_address

            if default_address.id == address.id:
                address_dict_list.insert(0, address_dict)
            else:
                address_dict_list.append(address_dict)

        default_id = request.user.default_address_id

        return JsonResponse({'code': 0,
                             'errmsg': 'ok',
                             'addresses': address_dict_list,
                             'default_address_id': default_id})

    def put(self, request, address_id):
        data = json.loads(request.body.decode())

        receiver = data.get('receiver')
        province_id = data.get('province_id')
        city_id = data.get('city_id')
        district_id = data.get('district_id')
        place = data.get('place')
        mobile = data.get('mobile')
        tel = data.get('tel')
        email = data.get('email')

        Address.objects.filter(pk=address_id).update(
            user=request.user,
            title=receiver,
            receiver=receiver,
            province_id=province_id,
            city_id=city_id,
            district_id=district_id,
            place=place,
            mobile=mobile,
            tel=tel,
            email=email
        )

        address = Address.objects.get(pk=address_id)
        address_dict = {
            "id": address.id,
            "title": address.title,
            "receiver": address.receiver,
            "province": address.province.name,
            "city": address.city.name,
            "district": address.district.name,
            "place": address.place,
            "mobile": address.mobile,
            "tel": address.tel,
            "email": address.email
        }

        return JsonResponse({'code': 0, 'errmsg': '地址修改成功', 'address': address_dict})

    def delete(self, request, address_id):
        try:
            address = Address.objects.get(pk=address_id)

            address.is_deleted = True
            address.save()
        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': "错误参数"})

        return JsonResponse({'code': 0, 'errmsg': ''})


class DefaultAddressView(LoginRequiredJsonMixin, View):

    def put(self, request, address_id):

        try:
            address = Address.objects.get(pk=address_id)

            request.user.default_address = address
            request.user.save()

        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': "错误参数"})

        return JsonResponse({'code': 0, 'errmsg': ''})


class UpdateTitleAddressView(LoginRequiredJsonMixin, View):
    def put(self, request, address_id):

        data = json.loads(request.body.decode())
        title = data.get('title')
        try:
            address = Address.objects.get(pk=address_id)

            address.title = title
            address.save()

        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': "错误参数"})

        return JsonResponse({'code': 0, 'errmsg': "0"})


class ChangePasswordView(LoginRequiredJsonMixin, View):

    def put(self, request):
        data = json.loads(request.body.decode())

        old_password = data.get('old_password')
        new_password = data.get('new_password')
        new_password2 = data.get('new_password2')

        if not all([old_password, new_password, new_password2]):
            return JsonResponse({'code': 400, 'errmsg': '参数错误'})

        user = request.user
        if not user.check_password(old_password):
            return JsonResponse({'code': 400, 'errmsg': '参数错误'})

        if new_password != new_password2:
            return JsonResponse({'code': 400, 'errmsg': '参数错误'})

        user.set_password(new_password)

        user.save()

        return JsonResponse({'code': 0, 'errmsg': ""})
